package com.jincp.image.compress;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.os.Build;
import android.os.Environment;
import android.text.TextUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

/**
 * Created by xiaoqi on 2016/12/27.
 */

public class ImageCompressProxy implements ImageCompress {

    private static ImageCompressProxy imageCompressInstance;

    private static Context mContext;

    private ImageCompress imageCompress;

    private static int DEFAULT_QUALITY = 50;

    private File compressFile;

    private ImageCompressProxy() {
        imageCompress = new ImageCompressWithJPEG();
    }

    public static ImageCompressProxy getInstance() {
        if (imageCompressInstance == null) {
            imageCompressInstance = new ImageCompressProxy();
        }
        return imageCompressInstance;
    }

    @Override
    public void init(Context context) {
        mContext = context.getApplicationContext();
        imageCompress.init(mContext);
        initCompressFile();
    }

    public void initCompressFile() {
        /**
         * 如果存在SD卡则将缓存写入SD卡,否则写入手机内存
         */
        try {
            File cacheDirectory = null;
            if (mContext.getExternalCacheDir() != null &&
                    Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                cacheDirectory = mContext.getExternalCacheDir().getCanonicalFile();
            } else {
                cacheDirectory = mContext.getCacheDir().getCanonicalFile();
            }
            compressFile = new File(cacheDirectory, "compress");
            if (!compressFile.exists()) {
                compressFile.mkdirs();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //压缩
    public void compressImage(String imagePath, ImageCompressListener listener) {
        if (TextUtils.isEmpty(imagePath)){
            if (listener != null) {
                listener.onCompressFailed(null, "image is null");
            }
            return;
        }
        File imageFile = new File(imagePath);
        if (!imageFile.exists()){
            if (listener != null) {
                listener.onCompressFailed(null, "image is null");
            }
            return;
        }
        String fileName = imageFile.getName();
        File newCompressFile = new File(compressFile, fileName);
        if (newCompressFile.exists()) newCompressFile.delete();
        compressImage(new ArrayList<>(Arrays.asList(imagePath)), DEFAULT_QUALITY, listener);
    }

    //压缩
    public void compressImage(List<String> imagePathList, ImageCompressListener listener) {
        imageCompress.compressImage(imagePathList, DEFAULT_QUALITY, listener);
    }

    //压缩
    @Override
    public void compressImage(List<String> imagePathList, int quality, ImageCompressListener listener) {
        if (imagePathList == null || imagePathList.isEmpty()){
            if (listener != null) {
                listener.onCompressFailed(imagePathList, "image is null");
            }
            return ;
        }
        imageCompress.compressImage(imagePathList, quality, listener);
    }

    public File createSaveFile() {
        File saveFile = new File(compressFile, generateFileName());
        try {
            if (!saveFile.exists()) {
                saveFile.getParentFile().mkdirs();
                saveFile.createNewFile();
            }
            return saveFile;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    private void saveBitmap(Bitmap bitmap, int quality, String savePath) {
        try {
            FileOutputStream fos = new FileOutputStream(savePath);
            bitmap.compress(Bitmap.CompressFormat.JPEG, quality, fos);
            fos.flush();
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static int getBitmapSize(Bitmap bitmap) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {    //API 19
            return bitmap.getAllocationByteCount();
        }
        return bitmap.getRowBytes() * bitmap.getHeight();//earlier version
    }

    public File getCompressFile() {
        return compressFile;
    }

    /**
     * 随机生产文件名
     *
     * @return
     */
    private static String generateFileName() {
        return UUID.randomUUID().toString() + ".jpg";
    }

    /**
     * 通过资源获取Bitmap防止OOM
     * @param resource 资源
     * @return bitmap
     */
    public Bitmap decodeBitmapFromResource(int resource){
        BitmapFactory.Options opt = new BitmapFactory.Options();
        opt.inPreferredConfig = Bitmap.Config.ARGB_8888;
        opt.inPurgeable = true;
        opt.inInputShareable = true;
        //获取资源图片
        InputStream is = mContext.getResources().openRawResource(resource);
        return BitmapFactory.decodeStream(is, null, opt);

    }

    /**
     * 通过文件路径读获取Bitmap防止OOM以及解决图片旋转问题
     * @param filePath 路径
     * @return bitmap
     */
    public static Bitmap decodeBitmapFromFile(String filePath){
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        newOpts.inJustDecodeBounds = true;//只读边,不读内容
        BitmapFactory.decodeFile(filePath, newOpts);
        int w = newOpts.outWidth;
        int h = newOpts.outHeight;
        // 获取尺寸压缩倍数
        newOpts.inSampleSize = getRatioSize(w,h);
        newOpts.inJustDecodeBounds = false;//读取所有内容
        newOpts.inDither = false;
        newOpts.inPurgeable=true;
        newOpts.inInputShareable=true;
        newOpts.inTempStorage = new byte[32 * 1024];
        Bitmap bitmap = null;
        File file = new File(filePath);
        FileInputStream fs = null;
        try {
            fs = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        try {
            if(fs!=null){
                bitmap = BitmapFactory.decodeFileDescriptor(fs.getFD(),null,newOpts);
                //旋转图片
                int photoDegree = readPictureDegree(filePath);
                if(photoDegree != 0){
                    Matrix matrix = new Matrix();
                    matrix.postRotate(photoDegree);
                    // 创建新的图片
                    bitmap = Bitmap.createBitmap(bitmap, 0, 0,
                            bitmap.getWidth(), bitmap.getHeight(), matrix, true);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally{
            if(fs!=null) {
                try {
                    fs.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return bitmap;
    }


    /**
     * 计算缩放比
     * @param bitWidth 当前图片宽度
     * @param bitHeight 当前图片高度
     * @return int 缩放比
     * @author XiaoSai
     * @since  2016年3月21日 下午3:03:38
     */
    private static int getRatioSize(int bitWidth, int bitHeight) {
        // 图片最大分辨率
        int imageHeight = 1280;
        int imageWidth = 960;
        // 缩放比
        int ratio = 1;
        // 缩放比,由于是固定比例缩放，只用高或者宽其中一个数据进行计算即可
        if (bitWidth > bitHeight && bitWidth > imageWidth) {
            // 如果图片宽度比高度大,以宽度为基准
            ratio = bitWidth / imageWidth;
        } else if (bitWidth < bitHeight && bitHeight > imageHeight) {
            // 如果图片高度比宽度大，以高度为基准
            ratio = bitHeight / imageHeight;
        }
        // 最小比率为1
        if (ratio <= 0)
            ratio = 1;
        return ratio;
    }

    /**
     * 读取图片属性：旋转的角度
     * @param path 图片绝对路径
     * @return degree旋转的角度
     */

    private static int readPictureDegree(String path) {
        int degree = 0;
        try {
            ExifInterface exifInterface = new ExifInterface(path);
            int orientation = exifInterface.getAttributeInt(
                    ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    degree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    degree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    degree = 270;
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return degree;
    }

    public static String getFileSize(long size) {
        if (size <= 0) {
            return "0B";
        }
        final String[] units = new String[]{"B", "KB", "MB", "GB", "TB"};
        int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
        return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
    }
}
